package edu.scsu.csci.validator;

import java.lang.annotation.Annotation;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import edu.scsu.csci.annotation.validator.ACharValidator;
import edu.scsu.csci.annotation.validator.ADateValidator;
import edu.scsu.csci.annotation.validator.ADoubleValidator;
import edu.scsu.csci.annotation.validator.AFloatValidator;
import edu.scsu.csci.annotation.validator.AIntegerValidator;
import edu.scsu.csci.annotation.validator.ANullValidator;
import edu.scsu.csci.annotation.validator.AShortValidator;
import edu.scsu.csci.annotation.validator.AStringValidator;
import edu.scsu.csci.core.IRegistry;

/**
 *
 * @author Maqbool Khan
 * @since jdk 1.5
 * @see
 */
public class TypeAnnotationRegistry implements IRegistry<Class<?>, Class<? extends Annotation>> {

	/**
	 * all the defined validation annotations along with the types for which they define the
	 * validation rules.
	 */
	private Map<Class<?>, Class<? extends Annotation>> registry;
	
	/**
	 * singleton instance.
	 */
	private static TypeAnnotationRegistry instance;
	
	/**
	 * returns the singleton instance.
	 */
	public synchronized static TypeAnnotationRegistry getInstance(){
		if(instance == null){
			instance = new TypeAnnotationRegistry();
			instance.setUp();
		}
		return instance;
	}
	/**
	 * @param type
	 * @param annotation
	 */
	private TypeAnnotationRegistry() {
		registry = new HashMap<Class<?>, Class<? extends Annotation>>();
	}
	
	/* (non-Javadoc)
	 * @see edu.scsu.csci.validator.IRegistry#register(java.lang.Class, java.lang.Class)
	 */
	public void register(Class<?> type, Class<? extends Annotation> annotationType){
		if(type == null || annotationType == null){
			throw new IllegalArgumentException("Neither of the parameters can be null. type: " + type 
						+ "\t annotationType: " + annotationType);
		}
		this.registry.put(type, annotationType);
	}
	
	/* (non-Javadoc)
	 * @see edu.scsu.csci.validator.IRegistry#get(java.lang.Class)
	 */
	public Class<? extends Annotation> get(Class<?> type){
		if(type == null){
			throw new IllegalArgumentException("Type " + type + " cannot be null.");
		}
		
		Class<? extends Annotation> annotationClass = this.registry.get(type);
		if(annotationClass == null){
			return ANullValidator.class;
		}
		return annotationClass;
	}
	
	/**
	 * initializes the registry.
	 */
	public void setUp(){
		this.register(String.class, AStringValidator.class);
		this.register(Integer.class, AIntegerValidator.class);
		this.register(int.class, AIntegerValidator.class);
		this.register(Double.class, ADoubleValidator.class);
		this.register(double.class, ADoubleValidator.class);
		this.register(Date.class, ADateValidator.class);
		this.register(Object.class, ANullValidator.class);
		this.register(Character.class, ACharValidator.class);
		this.register(Short.class, AShortValidator.class);
		this.register(Float.class, AFloatValidator.class);
	}
}
